<template>
  <div class="w-full h-full overflow-hidden relative" @touchstart="closeChatOpen">
    <template v-if="roomState.chatLoading && roomState.messages.length == 0">
      <div class="w-full h-[56px] flex justify-center items-center my-[3px]">
        <van-loading type="spinner" color="#000" size="26" />
      </div>
    </template>

    <virtual-list
      ref="virtualListRef"
      :list="roomState.messages"
      @is-scroll-bottom="isScrollBottom"
    >
      <template #default="{ source }: { source: GameHistoryMo }">
        <div
          class="chat-box"
          :class="{
            'mine-chat-box': isMine(source)
          }"
        >
          <template v-if="!isMine(source)">
            <!-- 头像 -->
            <div class="w-[38px] h-[38px] mt-[5px]">
              <img
                class="w-[38px] h-[38px] bg-[#ddd] rounded-[38px]"
                :src="netAvatar(source.avatar)"
              />
            </div>
          </template>
          <div
            class="flex-1 w-0"
            :class="{
              'mr-[50px] ml-[10px]': !isMine(source),
              'mr-[10px] ml-[50px]': isMine(source)
            }"
          >
            <!-- 名称 -->
            <div :class="{ 'flex justify-end': isMine(source) }">
              <div :class="['chat-name', { vip: isV(source) }]">
                {{ source.nick_name || "--" }}
              </div>
            </div>
            <!-- 内容 -->
            <div
              class="relative"
              :class="{
                'flex justify-end': isMine(source)
              }"
            >
              <template
                v-if="
                  source.msg_type == SocketMsgType.room_text_msg ||
                  source.msg_type == SocketMsgType.room_guessing_msg
                "
              >
                <div class="chat-message break-all line-break">
                  <div v-html="formatContent(source.content)"></div>
                  <div class="chat-timer">
                    {{ formatDate(source.time, "HH:mm:ss") }}
                  </div>
                </div>
              </template>
              <template v-else-if="source.msg_type == SocketMsgType.img_msg">
                <div class="chat-message">
                  <div class="bg-[#f5f7fa] flex justify-center w-[220px] h-[144px]">
                    <van-image
                      width="100%"
                      height="100%"
                      fit="contain"
                      :src="netPath(source.content)"
                      @click="handlePreview(netPath(source.content))"
                    />
                  </div>
                  <div class="chat-timer">
                    {{ formatDate(source.time, "HH:mm:ss") }}
                  </div>
                </div>
              </template>
              <template v-else-if="source.msg_type == SocketMsgType.red_msg">
                <div class="chat-message red-chat-message">
                  <div
                    class="w-[220px] h-[85px] flex justify-between items-center bg-[#E34F48] rounded-[6px]"
                  >
                    <img
                      class="w-[50px] h-[55px] ml-[5px]"
                      src="@/assets/images/room/msg-red.png"
                    />
                    <div class="flex-1 w-0 ml-[2px] mr-[10px]">
                      <div class="text-[15px] text-[#fff] truncate">{{ source.data.Remark }}</div>
                      <div class="text-[13px] text-[#ef9c99] mt-[6px]">您收到一个万利红包</div>
                    </div>
                  </div>
                  <div class="chat-timer">
                    {{ formatDate(source.time, "HH:mm:ss") }}
                  </div>
                </div>
              </template>
            </div>
          </div>
          <template v-if="isMine(source)">
            <div class="w-[38px] h-[38px] mt-[5px]">
              <img
                class="w-[38px] h-[38px] bg-[#ddd] rounded-[38px]"
                :src="netAvatar(source.avatar)"
              />
            </div>
          </template>
        </div>
      </template>
    </virtual-list>
    <div @click="scrollToBottom()" v-if="showChatMore" class="chat-more">
      <van-badge :content="unreadMessage" :offset="[-5, 5]">
        <div class="chat-more-icon">
          <svg-icon name="down" class="!text-[20px]" color="#3976cc"></svg-icon>
        </div>
      </van-badge>
    </div>
    <van-popup
      v-model:show="showDetail"
      closeable
      :style="{
        width: '100%',
        borderRadius: '8px'
      }"
    >
      <div class="w-full h-full box-border p-[15px]">
        <div class="text-[16px]">
          <span>注单详情</span>
        </div>
        <div class="flex justify-between flex-col mt-[15px]">
          <div class="text-[14px] flex border text-center bg-[#e3e5f1] !border-[#ccc]">
            <div class="flex-1 py-[10px] border-right !border-[#ccc]">位置</div>
            <div class="flex-1 py-[10px] border-right !border-[#ccc]">号码</div>
            <div class="flex-1 py-[10px]">金额</div>
          </div>
          <ul class="max-h-[400px] overflow-y-auto border-bottom !border-[#ccc]">
            <template v-for="item in detail">
              <li class="text-[14px] flex border text-center !border-t-0 !border-[#ccc]">
                <div class="flex-1 py-[10px] border-right !border-[#ccc]">{{ item.Cat2 }}</div>
                <div class="flex-1 py-[10px] border-right !border-[#ccc]">{{ item.Cat3 }}</div>
                <div class="flex-1 py-[10px]">{{ item.Amount }}</div>
              </li>
            </template>
          </ul>
        </div>
      </div>
    </van-popup>
  </div>
</template>
<script lang="ts" setup>
import $bus from "@/utils/bus";
import VirtualList from "@/components/virtual-list.vue";

import { cloneDeep } from "lodash-es";
import { showImagePreview } from "vant";
import { useUserStore } from "@/store/modules/user";
import { storeToRefs } from "pinia";
import { formatDate, netPath, netAvatar } from "@/utils/common";
import { debounce } from "lodash-es";
import { SocketMsgType } from "@/enums";
import { reqChatHistory } from "@/api/main";
import axios from "axios";
import { useSocketStore } from "@/store/modules/socket";
import { toast } from "@/utils/toast";

interface Detail {
  Cat2: string;
  Cat3: string;
  Amount: number;
}

const gameDetail = inject("gameDetail") as ComputedRef<GameTotalMo>;
const roomState = inject("roomState") as RoomState;
const socket = useSocketStore();
const userStore = useUserStore();
const { userInfo, chatToken } = storeToRefs(userStore);
const virtualListRef = ref();
const showDetail = ref(false);
const detail = ref<Detail[]>([]);

const unreadMessage = computed(() => {
  if (roomState.unreadMessage == 0) {
    return "";
  } else if (roomState.unreadMessage > 99) {
    return "99+";
  }
  return roomState.unreadMessage;
});

const showChatMore = computed(() => {
  if (!roomState.autoScrollToBottom) {
    return true;
  } else {
    return false;
  }
});

let cancelToken: any = null;

// 获取记录
const getData = async () => {
  // 如果有未完成的请求，取消它
  if (cancelToken) {
    cancelToken.cancel("Operation canceled by the user.");
  }
  cancelToken = axios.CancelToken.source();
  roomState.chatLoading = true;
  try {
    const res = await reqChatHistory(
      {
        LotteryId: gameDetail.value.LotteryId,
        Page: 1,
        PageSize: 200
      },
      cancelToken.token
    );
    roomState.messages = res.data || [];
    roomState.chatLoading = false;
    setTimeout(() => {
      scrollToBottom();
    }, 200);
  } catch (error) {
    roomState.chatLoading = false;
    console.log(error);
  }
};

// 设置为是否滚动到底部
const isScrollBottom = (flag: boolean) => {
  roomState.autoScrollToBottom = flag;
};

const closeChatOpen = () => {
  roomState.moreOpen = false;
};
// 图片预览
const handlePreview = (content: string) => {
  showImagePreview([content]);
};

// 处理消息体
const formatContent = (content?: string) => {
  if (!content) return "";
  let html = formatString(content);
  return html.replace(/\n/g, "<br />");
};

const formatString = (input: string) => {
  // 匹配字符串开头的 @ 开头并以空格结束的用户名
  const usernamePattern = /^(@\S+)\s/;
  // 匹配 '当前积分:' 后的数字
  const scorePattern = /当前积分:(\d*\.?\d+)/;
  // 匹配 '本次竞猜总分:' 后的数字
  const totalScorePattern = /本次竞猜总分:(\d*\.?\d+)/;
  // 匹配 '最低限额:' 后的数字
  const minPattern = /最低限额:(\d*\.?\d+)/;
  // 匹配 '最高限额:' 后的数字
  const maxPattern = /最高限额:(\d*\.?\d+)/;
  // 匹配 '总元宝:' 后的数字
  const totalYuanbaoPattern = /总元宝:(\d*\.?\d+)/;
  // 匹配 '汇总：' 后的数字
  const summaryPattern = /(汇总：)(\d*\.?\d+)/g;
  //替换 '第x名[' 和 '/' 之间的数字或中文
  const multiRankPattern = /(\[)([\S\s]*?\/\d+\.?\d*)(\])/g;

  // 替换用户名
  const formattedUsername = input.replace(
    usernamePattern,
    "<span class='text-[#2CFF6B]'>$1</span> "
  );
  // 替换当前积分
  const formattedScore = formattedUsername.replace(
    scorePattern,
    "当前积分:<span class='text-yellow-500'>$1</span>"
  );
  // 替换本次竞猜总分
  const formattedTotalScore = formattedScore.replace(
    totalScorePattern,
    "本次竞猜总分:<span class='text-yellow-500'>$1</span>"
  );
  // 替换最低限额
  const minScore = formattedTotalScore.replace(
    minPattern,
    "最低限额:<span class='text-yellow-500'>$1</span>"
  );
  // 替换最高限额
  const maxScore = minScore.replace(maxPattern, "最高限额:<span class='text-yellow-500'>$1</span>");
  // 替换总元宝
  const totalYuanbao = maxScore.replace(
    totalYuanbaoPattern,
    "总元宝:<span class='text-yellow-500'>$1</span>"
  );
  // '汇总：' 后的数字
  const summary = totalYuanbao.replace(summaryPattern, "$1<span class='text-yellow-500'>$2</span>");
  // 替换结尾的数字
  const formattedEnd = summary.replace(multiRankPattern, function (_match, p1, p2, p3) {
    const parts = p2.split(" ");
    const formattedParts = parts.map((part: string) =>
      part.replace(/(\/)(\d+)/, "$1<span class='text-yellow-500'>$2</span>")
    );
    return p1 + formattedParts.join(" ") + p3;
  });
  const outtext = formattedEnd.replace(
    /<a\s+(data='[^']*')>.*?<\/a>/g,
    `<span class="text-yellow-500 detail cursor-pointer" $1>注单详情</span>`
  );
  return outtext;
};

// 滚动到底部
const scrollToBottom = () => {
  virtualListRef.value?.scrollToBottom();
  roomState.unreadMessage = 0;
  nextTick(() => {
    setDomClick();
  });
};

// 是否为自己
const isMine = (item: GameHistoryMo) => {
  if (
    Number(userInfo.value?.RoomId) === Number(item.user_id) ||
    Number(item.user_id) === 0 ||
    `r_${userInfo.value?.RoomId}` === String(item.user_id)
  ) {
    return true;
  }
  return false;
};

const isV = (item: GameHistoryMo) => {
  if (typeof item.user_id === "string" && String(item.user_id).search("r_") != -1) {
    return true;
  }
  return false;
};

// 处理注单点击事件
const setDomClick = () => {
  document.querySelectorAll(".chat-message .detail").forEach((dom: any) => {
    if (dom) {
      dom.onclick = () => {
        detail.value = JSON.parse(dom.getAttribute("data"));
        nextTick(() => {
          showDetail.value = true;
        });
      };
    }
  });
};

// 发送消息
const handleSend = () => {
  if (!roomState.chatContent) {
    toast.info("内容不能为空");
    return;
  }
  const roomName = `${userInfo.value?.RoomId}_${roomState.gameId}`;
  const sendData = {
    token: chatToken.value,
    roomName, // 房间ID
    content: roomState.chatContent,
    msgType: 2,
    width: 0,
    height: 0,
    sendType: "PUBLIC",
    customize: "",
    thumb: ""
  };
  socket.client?.emit("send_msg", sendData);
  roomState.chatContent = "";
};

// 加入房间
const joinRoom = (gameId: number) => {
  const roomName = `${userInfo.value?.RoomId}_${gameId}`;
  socket.client?.emit("joinroom", {
    roomName,
    userId: userInfo.value?.Id,
    nickName: userInfo.value?.Name,
    sendType: "PUBLIC"
  });
};

// 退出房间
const outRoom = (gameId: number) => {
  const roomName = `${userInfo.value?.RoomId}_${gameId}`;
  socket.client?.emit("leaveroom", { roomName });
};

const watchSocket = () => {
  // 监听房间消息
  $bus.on("room-msg", async (data: GameHistoryMo) => {
    let obj = cloneDeep(data);
    let messages = cloneDeep(roomState.messages);
    messages.push({
      ...obj
    });
    if (messages.length >= 600) {
      messages = messages.slice(200, messages.length + 1);
    }
    roomState.messages = cloneDeep(messages);
    await nextTick();
    if (showChatMore.value) {
      roomState.unreadMessage++;
    } else {
      setTimeout(() => {
        $bus.emit("chat-scroll-to-bottom");
      }, 300);
    }
  });
  $bus.on("updata-history-list", () => {
    getData();
  });
  $bus.on(
    "chat-scroll-to-bottom",
    debounce(() => {
      let count = 0;
      if (roomState.autoScrollToBottom) {
        let timer: any = setInterval(() => {
          count++;
          if (count < 50) {
            virtualListRef.value?.scrollToBottom();
            setDomClick();
          } else {
            clearInterval(timer);
            timer = null;
            count = 0;
            setDomClick();
          }
        }, 1);
      }
    }, 400)
  );
};

watch(
  () => roomState?.moreOpen,
  () => {
    scrollToBottom();
  }
);

watch(
  () => roomState.gameId,
  (val, old) => {
    outRoom(old);
    roomState.messages = [];
    getData().finally(() => {
      joinRoom(val);
    });
  }
);

onMounted(() => {
  watchSocket();
  getData().finally(() => {
    joinRoom(roomState.gameId);
  });
});
onBeforeUnmount(() => {
  outRoom(roomState.gameId);
});

defineExpose({
  send: handleSend
});
</script>
<style lang="scss" scoped>
.chat-box {
  margin: 0 10px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  overflow: hidden;
}
.vip {
  font-weight: 600;
  position: relative; /* 添加定位 */
}

.vip::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -14px;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  background: url("@/assets/images/room/chat-v.png") no-repeat center center;
  background-size: contain;
}
.mine-chat-box {
  .chat-name {
    color: #666;
    background-color: transparent;
  }

  .chat-message {
    background-color: #5396de;
    color: #fff;
    .chat-timer {
      color: #fff;
    }
    &::after {
      content: "";
      position: absolute;
      width: 0px;
      height: 0px;
      right: -13px;
      left: auto;
      top: 10px;
      border: 7px solid transparent;
      border-left: 7px solid #5396de;
    }
  }
}
.chat-message {
  &::after {
    content: "";
    position: absolute;
    width: 0px;
    height: 0px;
    left: -13px;
    top: 10px;
    border: 7px solid transparent;
    border-right: 7px solid #fff;
  }
  :deep() {
    a {
      color: #198cff;
      margin-left: 5px;
      display: inline-block;
    }
  }
}
.red-chat-message {
  padding: 0 !important;
  .chat-timer {
    color: #ef9c99;
  }
  &::after {
    border-right: 7px solid #e34f48;
  }
}
</style>
<style lang="css" scoped>
.chat-name {
  @apply h-[18px] leading-[18px] px-[5px] rounded-[4px] inline-block text-[13px] text-[#666] mb-[4px];
}
.chat-message {
  @apply bg-[#fff] break-all inline-block p-[10px] pb-[15px] mb-[10px] rounded-[6px] relative text-[14px] min-w-[60px];
}
.chat-timer {
  @apply absolute bottom-[2px] right-[5px] text-[10px] text-[#999];
}
.chat-follow-timer {
  @apply absolute bottom-[24px] right-[5px] text-[10px] text-[#999];
}
.chat-follow {
  @apply absolute bottom-[0px] right-[0px] w-[50px] h-[24px] leading-[24px] bg-[#ff0000] text-[#fff] rounded-tl-[6px] rounded-br-[6px] text-center;
  background: linear-gradient(90deg, #3893cc, #62aee1);
}
.chat-more {
  @apply absolute bottom-[15px] right-[15px] z-50;
}
.chat-more-icon {
  @apply h-[40px] w-[40px] bg-[#fff] rounded-full;
  @apply flex justify-center items-center shadow-md;
}
</style>
